﻿using System;
using System.Collections.Generic;
using System.Management.Automation.Provider;
using System.Management.Automation;
using System.Reflection;
using System.Text;

using Sitecore.Configuration;
using Sitecore.Data;
using Sitecore.Data.Fields;
using Sitecore.Data.Items;
using Sitecore.Globalization;
using Sitecore.Publishing;
using Sitecore.Publishing.Pipelines.PublishItem;

namespace Cognifide.PowerShell.Shell
{
    public static class ItemShellExtensions
    {
        private static Dictionary<ID,List<string>> allPropertySets =  new Dictionary<ID, List<string>>();

        private static Dictionary<string, string> customGetters = new Dictionary<string, string>()
                                                                      {
                                                                          {"ItemPath", "$this.Paths.Path"},
                                                                          {"FullPath", "$this.Paths.FullPath"},
                                                                          {"MediaPath", "$this.Paths.MediaPath"},
                                                                          {"ContentPath","$this.Paths.ContentPath"}
                                                                      };

        internal static PSObject GetPSObject(CmdletProvider provider, Item item)
        {
            PSObject psobj = PSObject.AsPSObject(item);

            List<string> propertySet;
            if (allPropertySets.ContainsKey(item.TemplateID))
            {
                propertySet = allPropertySets[item.TemplateID];
            }
            else
            {
                item.Fields.ReadAll();
                propertySet = new List<string>(item.Fields.Count);
                foreach (Field field in item.Fields)
                {
                    if (field.Name != "ID")// don't map - native property
                    {
                        propertySet.Add(field.Name);
                    }
                }
                allPropertySets.Add(item.TemplateID, propertySet);
            }

            foreach (string field in propertySet)
            {
                if (!String.IsNullOrEmpty(field))
                {
                    //propertyName = UnderscorePropertyToCamelCase(propertyName);

                    bool duplicate = psobj.Properties[field] == null;
                    string getter = item.Fields[field].TypeKey == "datetime"
                                        ? String.Format("[Sitecore.DateUtil]::IsoDateToDateTime($this[\"{0}\"])", field)
                                        : String.Format("$this[\"{0}\"]", field);
                    string setter =
                        String.Format("[{0}]::Modify($this, \"{1}\", $Args );",
                                      typeof(ItemShellExtensions).FullName, field);

                    psobj.Properties.Add(new PSScriptProperty(
                                             duplicate ? field : String.Format("_{0}", field),
                                             provider.InvokeCommand.NewScriptBlock(getter),
                                             provider.InvokeCommand.NewScriptBlock(setter)));
                }
            }

            foreach (string customGetter in customGetters.Keys)
            {
                    psobj.Properties.Add(new PSScriptProperty(
                                             customGetter,
                                             provider.InvokeCommand.NewScriptBlock(customGetters[customGetter])));               
            }
            

            return psobj;
        }

        public static void Modify(PSObject psItem, string propertyName, object[] propertyValue)
        {
            Item item = psItem.ImmediateBaseObject as Item;
            if (item != null)
            {
                item.Edit(
                    args =>
                    {
                        if (propertyValue[0] is DateTime)
                        {
                            item[propertyName] = ((DateTime)propertyValue[0]).ToString("yyyyMMddTHHmmss");
                        }
                        else
                        {
                            item[propertyName] = propertyValue[0].ToString();
                        }
                    });
            }

        }

    }
}
